package fm

import (
	"fmt"
	"gitee.com/xluomo945/fm/helper"
	"gitee.com/xluomo945/fm/jwt"
	"gitee.com/xluomo945/fm/log"
	"gitee.com/xluomo945/fm/middleware"
	"gitee.com/xluomo945/fm/mini"
	"gitee.com/xluomo945/fm/route"
	"github.com/gin-gonic/gin"
	syslog "log"
	"net/http"
	"path/filepath"
	"runtime"
)

type RegisterRouteHandle func(route.RouterHandler) error

func (app *App) loadRouteGroup() error {
	// 创建GIN
	app.server = gin.New()

	// 设置公共中间件
	app.server.Use(app.recover())

	// 根据配置启动默认中间件
	if app.Middleware.UseTrace {
		app.server.Use(middleware.Trace)
	}
	if app.Middleware.SaveDataFlow && !helper.StringEmpty(string(app.LoggerConfig.Type)) {
		app.server.Use(middleware.DataFlow)
	}
	if app.Middleware.UseCors {
		app.server.Use(middleware.Cors)
	}

	// 设置jwt
	jwt.SetConfig(app.JwtConfig)

	// 没有传递路由注册函数进来
	if app.RegisterRoute == nil {
		syslog.Println("[Warn] route is empty")
		return nil
	}

	// 注册路由
	g := route.CreateRouter(app.server.Group(""))
	syslog.Println("[INFO] register route")
	if err := app.RegisterRoute(g); err != nil {
		return err
	}

	var tplFilenames []string

	// 文档查询器
	if app.MiniServer.Docs.OpenShowDocs {
		mini.CreateDocs()
		app.runDocsServer()
		tplFilenames = append(tplFilenames, docsFilename())
	}

	// 日志查询器
	if app.MiniServer.Logs.OpenShowLogs {
		app.runLogsServer()
		tplFilenames = append(tplFilenames, logsFilename())
		tplFilenames = append(tplFilenames, detailFilename())
	}

	if len(tplFilenames) > 0 {
		app.server.LoadHTMLFiles(tplFilenames...)
	}

	return nil
}

func (app *App) recover() gin.HandlerFunc {
	return gin.CustomRecovery(func(ctx *gin.Context, err any) {
		log.Fail(ctx, "run panic err: %s", err)
		ctx.AbortWithStatus(http.StatusInternalServerError)
	})
}

func (app *App) runDocsServer() {
	group := app.server.Group(helper.StringDefault(app.MiniServer.Docs.RouteGroupPrefix, "docs"))
	s := mini.CreateDocsServer()
	group.GET(fmt.Sprintf("%s", helper.StringDefault(app.MiniServer.Docs.DocsRoute, "show")), s.Show)
}

func (app *App) runLogsServer() {
	group := app.server.Group(helper.StringDefault(app.MiniServer.Logs.RouteGroupPrefix, "logs"))
	s := log.NewLogsServer(fmt.Sprintf("/%s/%s/:date", helper.StringDefault(app.MiniServer.Logs.RouteGroupPrefix, "logs"), helper.StringDefault(app.MiniServer.Logs.LogsRoute, "runtime")))
	group.GET(fmt.Sprintf("%s/:date/detail", helper.StringDefault(app.MiniServer.Logs.LogsRoute, "runtime")), s.Filter)
	group.GET(fmt.Sprintf("%s/:date", helper.StringDefault(app.MiniServer.Logs.LogsRoute, "runtime")), s.Show)
}

func logsFilename() string {
	_, b, _, _ := runtime.Caller(0)
	basePath := filepath.Dir(b)
	return filepath.Join(basePath, "tpl/runtime.tmpl")
}

func detailFilename() string {
	_, b, _, _ := runtime.Caller(0)
	basePath := filepath.Dir(b)
	return filepath.Join(basePath, "tpl/detail.tmpl")
}

func docsFilename() string {
	_, b, _, _ := runtime.Caller(0)
	basePath := filepath.Dir(b)
	return filepath.Join(basePath, "tpl/docs.tmpl")
}
